/*
 * @version: 0.0.1
 * @Author: 董正阳
 * @Date: 2019-11-13 11:07:50
 * @LastEditors  : 董正阳
 * @LastEditTime : 2020-01-02 14:59:36
 * @Description:
 */

var wr = (function () {
  // 准备工作
  function ready(callback) {
    // 如果是以apicloud形式打开
    if (isApi()) {
      apiready = function () {
        // 若没有frameName则代表当前页面是win，若有header标签或带有header类名或id的标签则需要打开沉浸式兼容
        var header = document.getElementsByClassName('header')[0] || document.getElementsByTagName('header')[0] || document.getElementById('header');
        if (!api.frameName && header) {
          statusBar();
        }
        // 优化点击事件
        api.parseTapmode();
        // 执行逻辑
        callback();
      }
    } else {
      window.onload = function () { // 防止pc在使用loading方法动态加载资源而导致资源没找到的兼容
        // 执行逻辑
        callback();
      }
    }
  }


  // 判断是否apicloud环境
  function isApi() {
    var version = navigator.userAgent;
    if (version.indexOf("APICloud") != -1) {
      return true;
    } else {
      return false;
    }
  }

  // 打开一个指定路径的页面
  function openWin(path, page, pageParam) {
    api.openWin({
      name: page,
      url: 'widget://html/' + path + '/' + page + '.html',
      pageParam: pageParam,
      reload: true,
      bounces: false,
      bgColor: "#fff",
      allowEdit: true,
      softInputMode: 'auto',
      overScrollMode: 'always',
      vScrollBarEnabled: false,
      hScrollBarEnabled: false,
      animation: {
        type: "push", //动画类型（详见动画类型常量）
        subType: "from_right", //动画子类型（详见动画子类型常量）
        duration: 300 //动画过渡时间，默认300毫秒
      }
    });
  }

  // 打开一个指定路径并带有公共头部的页面
  function openCommonWin(pageFile, pageName, pageTitle, params, el) {
    api.openWin({
      name: pageName + '_page',
      url: 'widget://html/common/win-header.html',
      pageParam: {
        pageFile: pageFile,
        pageName: pageName,
        pageTitle: pageTitle,
        params: params,
        el: el
      },
      reload: true,
      bounces: false,
      bgColor: "#fff",
      scrollEnabled: true,
      slidBackEnabled: false,
      historyGestureEnabled: false,
      vScrollBarEnabled: false,
      hScrollBarEnabled: false,
      animation: {
        type: "push", //动画类型（详见动画类型常量）
        subType: "from_right", //动画子类型（详见动画子类型常量）
        duration: 300 //动画过渡时间，默认300毫秒
      }
    });
  }

  // 监听公共头部的自定义事件
  function listenHeadEvent(callback) {
    api.addEventListener({
      name: 'customEvent'
    }, function (ret, err) {
      if (ret) {
        if (api.frameName == ret.value.frameName) {
          callback(ret.value);
        }
      }
    });
  }

  // 打开一个指定url并带有公共头部的外链页面
  function openCommonUrl(url, pageTitle) {
    api.openWin({
      name: url + '_page',
      url: 'widget://html/common/win-header.html',
      pageParam: {
        pageFile: url,
        pageTitle: pageTitle
      },
      reload: true,
      bounces: false,
      bgColor: "#fff",
      scrollEnabled: true,
      slidBackEnabled: false,
      historyGestureEnabled: false,
      vScrollBarEnabled: false,
      hScrollBarEnabled: false,
      animation: {
        type: "push", //动画类型（详见动画类型常量）
        subType: "from_right", //动画子类型（详见动画子类型常量）
        duration: 300 //动画过渡时间，默认300毫秒
      }
    });
  }

  // 显示模态框
  function openModal(path, page, pageParam, settings) {
    // 模态框宽度，默认拉满
    var w = settings ? settings.width || 'auto' : 'auto';
    // 模态框高度，默认300
    var h = settings ? settings.height || 300 : 300;
    // 模态框距底部距离，默认0
    var bottom = settings ? settings.bottom || 0 : 0;
    // 模态框出现的动画持续时间，默认200
    var duration = settings ? settings.duration || 200 : 200;

    // 打开模态框
    api.openFrame({
      name: page,
      url: 'widget://html/' + path + '/' + page + '.html',
      rect: {
        w: w,
        h: h,
        marginBottom: bottom
      },
      bounces: false,
      vScrollBarEnabled: true,
      hScrollBarEnabled: true,
      animation: {
        type: "movein",
        subType: "from_bottom",
        duration: duration || 200
      },
      pageParam: pageParam
    });
  }

  // 检测登录状态，如无登录则跳转指定页面
  function ifLogin(path, page, pageParam) {
    var res;
    var token = getStorage('token');
    if (!token) {
      res = false;
      path && openWin(path, page, pageParam);
    } else {
      res = token;
    }
    return res;
  }

  // 弹一个toast
  function toast(msg, duration, location) {
    var duration = duration || 1500;
    var location = location || 'bottom';
    api.toast({
      msg: msg,
      duration: duration,
      location: location
    });
  }

  //没有内容的时候提醒
  function addLastInfo(param) {
    param = param || {};
    param.content = param.content || '暂无更多';
    param.bg = param.bg || 'transparent';
    param.color = param.color || '#666';
    param.el = document.querySelector(param.el) || document.querySelector('.content-list');
    if (!document.querySelector('.lastinfo')) {
      if (param.oldRem) {
        param.el.insertAdjacentHTML('afterend', '<div id="lastinfo" style="width:100%;height:1rem;text-align:center;line-height:1rem;font-size:.32rem;color:'
          + param.color + ';background:' + param.bg + ' !important;transform:scaleX(2.5) scaleY(2.5);">' + param.content + '</div>');
      } else {
        param.el.insertAdjacentHTML('afterend', '<div id="lastinfo" style="width:100%;height:1rem;text-align:center;line-height:1rem;font-size:.32rem;color:'
          + param.color + ';background:' + param.bg + ' !important;">' + param.content + '</div>');
      }
    }
  }

  // 删除没有内容时的提醒
  function removeLastInfo() {
    var el = document.getElementById('lastinfo');
    if (!el) return;
    el.parentNode.removeChild(el);
  }

  // 设置文本到粘贴板
  function setText(text) {
    // 需要引入clipBoard模块
    var clipBoard = api.require('clipBoard');
    clipBoard.set({
      value: text
    }, function (ret, err) {
      if (text.length <= 0) return;
      if (ret) {
        toast('复制成功');
      } else {
        toast('复制失败');
      }
    });
  }

  // 从粘贴板获取文本
  function getText(callback) {
    // 需要引入clipBoard模块
    var clipBoard = api.require('clipBoard');
    clipBoard.get(function (ret, err) {
      if (ret) {
        if (callback) {
          callback(ret.value);
        }
      } else {
        alert('获取失败');
      }
    });
  }

  // 选择一张能够裁剪的照片或图片
  function selClipPhoto(params, callback) {
    params = params || {};
    params.type = params.type || 0;
    params.isClip = params.isClip || 'y';
    params.style = params.style || {};
    types = ['camera', 'album'];
    api.getPicture({
      sourceType: types[params.type],
      encodingType: 'jpg',
      mediaValue: 'pic',
      allowEdit: false,
      quality: 96,
      saveToPhotoAlbum: false
    }, function (ret, err) {
      if (ret) {
        // 不需要裁剪
        if (params.isClip == 'n') {
          setTimeout(function () {
            callback(ret.data);
            return;
          }, 100);
        } else {
          // 需要裁剪
          if (!ret.data) return;
          picClip(ret.data, params.style);
          // 监听裁剪
          api.addEventListener({
            name: 'picClipFinish'
          }, function (ret, err) {
            if (ret) {
              callback(ret.value.path);
            }
          });
        }
      }
    });
  }

  // 图片裁剪
  function picClip(pic, style) {
    // 需要引入FNImageClip模块
    var FNImageClip = api.require('FNImageClip');
    style.bg = style.bg || '#f5f5f5';
    style.btnBg = style.btnBg || '#E5502E';
    style.color = style.color || '#fff';
    var el = "<div style='position:fixed;bottom:0;left:0;z-index:9999;width:100%;height:1.5rem;background:" + style.bg + ";display:flex;flex-direction:column;justify-content:center;align-items:center;font-size:.3rem;' id='clip-box'>" +
      "<div id='clip-btn' style='width:80%;height:.8rem;border-radius:.5rem;background:" + style.btnBg + ";text-align:center;line-height:.8rem;color:" + style.color + ";' tapmode onclick='wr._picClipSave()'>上传头像</div></div>";
    document.getElementsByTagName('body')[0].insertAdjacentHTML('beforeend', el);
    FNImageClip.open({
      rect: {
        x: 0,
        y: 0,
        w: api.winWidth,
        h: api.winHeight - document.querySelector('#clip-box').offsetHeight
      },
      srcPath: pic,
      mode: 'image',
      style: {
        mask: 'rgba(0,0,0,0.75)',
        clip: {
          w: 200,
          h: 200,
          x: (api.frameWidth - 200) / 2,
          y: (api.frameHeight - 200) / 2,
          borderColor: '#0f0',
          borderWidth: 1,
          appearance: 'rectangle'
        }
      },
    }, function (ret, err) { });
  }

  // 图片裁剪保存(私有)
  function _picClipSave() {
    // 需要引入FNImageClip模块
    var FNImageClip = api.require('FNImageClip');
    var timeStamp = new Date().getTime();
    FNImageClip.save({
      destPath: 'fs://wr_' + timeStamp + '.jpg',
      copyToAlbum: false,
      quality: 1
    }, function (ret, err) {
      // 通知已经裁剪完毕
      api.sendEvent({
        name: 'picClipFinish',
        extra: {
          path: ret.destPath
        }
      });
      // 移除裁剪ui
      FNImageClip.close();
      var clipBox = document.getElementById('clip-box') || false;
      if (clipBox) {
        clipBox.parentNode.removeChild(clipBox);
      }
    });
  }

  // 选择多个媒体
  function selMoreMedia(params, callback) {
    var typeList = ['all', 'image', 'video'];
    var picBox = [];
    params = params || {};
    params.type = params.type || 1;
    params.max = params.max || 9;
    // 需要引入UIAlbumBrowser模块
    var UIAlbumBrowser = api.require('UIAlbumBrowser');
    UIAlbumBrowser.open({
      type: typeList[params.type],
      max: params.max,
      isOpenPreview: true,
      styles: {
        bg: '#fff',
        mark: {
          icon: '',
          position: 'bottom_left',
          size: 25
        },
        nav: {
          bg: 'rgba(0,0,0,0.6)',
          titleColor: '#fff',
          titleSize: 20,
          cancelColor: '#fff',
          cancelSize: 20,
          finishColor: '#fff',
          finishSize: 20
        }
      },
      rotation: false
    }, function (ret) {
      if (ret) {
        // 点击完成
        if (ret.eventType == 'confirm') {
          var cachePics = ret.list;
          // iOS需要转化路径
          for (var i = 0; i < cachePics.length; i++) {
            UIAlbumBrowser.transPath({
              path: cachePics[i].path
            }, function (ret, err) {
              if (ret) {
                picBox.push(ret.path);
              }
            });
          }
          // 如果都已转化完成则返回这些图片
          var t = setInterval(function () {
            if (picBox.length == cachePics.length) {
              clearInterval(t);
              callback(picBox);
            }
          });
        }
      }
    });
  }

  // 长按保存图片
  function longpress(duration) {
    // 想要触发长按存图，需要为目标图片添加此类
    var picArr = document.querySelectorAll('.download-pic');
    var picUrl = '';
    var timer;
    duration = duration || 500;
    // 如果没有目标
    if (!picArr || !picArr.length) {
      toast("没有图片");
      return;
    }
    // 为每个图片添加事件
    for (var i = 0; i < picArr.length; i++) {
      picArr[i].addEventListener('touchstart', function () {
        // 记录当前图片路径
        picUrl = this.src;
        // 获取时间戳
        var timestamp = new Date().getTime();
        // 长按
        timer = setTimeout(function () {
          api.actionSheet({
            title: '请选择',
            cancelTitle: '取消',
            buttons: [
              '保存图片'
            ]
          }, function (ret, err) {
            if (ret) {
              if (ret.buttonIndex == 1) {
                // 保存图片
                downloadPic(picUrl, timestamp)
              }
            }
          });
        }, duration);
      });
      // 半途松开销毁长按事件
      picArr[i].addEventListener('touchend', function () {
        clearTimeout(timer);
      })
    }
  }

  // 下载图片
  function downloadPic(picUrl, timestamp) {
    api.download({
      url: picUrl,
      savePath: 'fs://image/master' + timestamp + '.jpg'
    }, function (ret, err) {
      if (ret) {
        if (ret.state == 1) {
          api.saveMediaToAlbum({
            path: 'fs://image/master' + timestamp + '.jpg'
          }, function (ret) {
            if (ret && ret.status) {
              api.toast({
                msg: '成功保存到相册',
                duration: 2000,
                location: 'bottom'
              });
            } else {
              alert('保存失败');
            }
          });
        }
      } else {
        console.log(JSON.stringify(err));
      }
    });
  }

  // 微信分享网页 (需要微信模块)
  function shareWxWeb(params) {
    var modeArr = ['session', 'timeline', 'favorite']; // 会话 朋友圈 收藏
    params = params || {};
    params.mode = params.mode || 0;
    params.title = params.title || '分享头部';
    params.description = params.description || '分享内容';
    params.thumb = params.thumb || '';
    params.link = params.link || '';
    var wxPlus = api.require('wxPlus');
    wxPlus.shareWebpage({
      apiKey: '',
      scene: modeArr[params.mode],
      title: params.title,
      description: params.description,
      thumb: params.thumb,
      contentUrl: params.link
    }, function (ret, err) {
      if (ret.status) {
      } else {
        alert(err.code);
      }
    });
  }

  // QQ分享网页 (需要QQ模块)
  function shareQQWeb(params) {
    var modeArr = ['QFriend', 'QZone']; // 会话 qq空间
    params = params || {};
    params.mode = params.mode || 0;
    params.title = params.title || '分享头部',
      params.description = params.description || '分享内容';
    params.thumb = params.thumb || '';
    params.link = params.link || '';
    var qq = api.require('QQPlus');
    qq.shareNews({
      url: params.link,
      title: params.title,
      description: params.description,
      imgUrl: params.thumb,
      type: modeArr[params.mode]
    }, function (ret, err) {
      if (ret.status) {
      } else {
        alert(err.code);
      }
    });
  }

  // 微信支付（需要微信支付模块）
  function wxPay(data, info, callback) {
    var wxPay = api.require('wxPayPlus');
    wxPay.payOrder({
      apiKey: data.appid,
      orderId: data.prepayid,
      mchId: data.partnerid,
      nonceStr: data.noncestr,
      timeStamp: data.timestamp,
      package: data.package,
      sign: data.sign
    }, function (ret, err) {
      if (ret.status) {
        wr.toast(info, 3000, 'middle');
        callback();
      } else if (err.code == '-2') {
        wr.toast('支付失败', 3000, 'middle');
      } else if (err.code == '1') {
        wr.toast('apiKey值非法', 3000, 'middle');
      } else if (err.code == '-1') {
        wr.toast('未知错误', 3000, 'middle');
      }
    });
  }

  // 支付宝支付(需要模块)
  function aliPay(data, callback) {
    var aliPayPlus = api.require('aliPayPlus');
    aliPayPlus.payOrder({
      orderInfo: data.str
    }, function (ret, err) {
      var code = ret.code;
      switch (code) {
        case '9000':
          wr.toast('支付成功!', 3000, 'middle');
          callback();
          break;
        case '8000':
          wr.toast('支付结果未知（有可能已经支付成功），请查询您的支付状态!', 3000, 'middle');
          break;
        case '4000':
          wr.toast('订单支付失败', 3000, 'middle');
          break;
        case '5000':
          wr.toast('重复请求', 3000, 'middle');
          break;
        case '6001':
          wr.toast('用户中途取消支付操作', 3000, 'middle');
          break;
        case '6002':
          wr.toast('网络连接出错', 3000, 'middle');
          break;
        case '6004':
          wr.toast('支付结果未知（有可能已经支付成功），请查询您的支付状态', 3000, 'middle');
          break;
        default:
          wr.toast('未知错误', 3000, 'middle');
      }
    });
  }

  // 打开签字板
  function openSignBoard(param, callback) {
    param = param || {};
    var width = api.winWidth - (param.marginLR || 36);
    var height = param.height || 140;
    var high = api.winHeight - height - 63;
    var both = param.marginLR / 2 || 36 / 2;
    param.style = param.style || {};
    param.style.bg = param.style.bg || 'transparent !important';
    param.style.btnBg1 = param.style.btnBg1 || '#f8b303 !important';
    param.style.btnColor1 = param.style.btnColor1 || '#fff !important';
    param.style.btnBg2 = param.style.btnBg2 || '#454648 !important';
    param.style.btnColor2 = param.style.btnColor2 || '#fff !important';
    // 需要引入drawingBoard模块
    var drawingBoard = api.require('drawingBoard');
    drawingBoard.open({
      rect: {
        x: both,
        y: high,
        w: width,
        h: height
      },
      styles: {
        brush: {
          color: '#333',
          width: 4
        },
        bgColor: '#fff'
      }
    });
    var el = "<div style='position:fixed;bottom:0;left:0;z-index:9999;width:100%;height:1.3rem;background:" + param.style.bg + ";display:flex;justify-content:space-around;align-items:center'>" +
      "<div style='width:2rem;height:.8rem;border-radius:.4rem;background:" + param.style.btnBg1 + ";text-align:center;line-height:.8rem;color:" + param.style.btnColor1 + ";' tapmode onclick='wr._reSignBoard()'>重置签名</div>" +
      "<div style='width:2rem;height:.8rem;border-radius:.4rem;background:" + param.style.btnBg2 + ";text-align:center;line-height:.8rem;color:" + param.style.btnColor2 + ";' tapmode onclick='wr._closeSignBoard()'>上传签名</div>" +
      "</div>";
    document.getElementsByTagName('body')[0].insertAdjacentHTML('beforeend', el);
    // 监听返回结果
    api.addEventListener({
      name: 'signFinish'
    }, function (ret, err) {
      if (ret) {
        callback(ret.value.path);
      }
    });
  }

  // 重置签字板
  function _reSignBoard() {
    // 需要引入drawingBoard模块
    var drawingBoard = api.require('drawingBoard');
    drawingBoard.clear();
  }

  // 关闭签字板
  function _closeSignBoard() {
    // 需要引入drawingBoard模块
    var drawingBoard = api.require('drawingBoard');
    drawingBoard.save({
      savePath: 'fs://drawingBoard/result.png',
      copyToAlbum: false
    }, function (ret) {
      var path = ret.absolutePath;
      api.sendEvent({
        name: 'signFinish',
        extra: {
          path: path
        }
      });
    });
  }

  // 图片查阅器 路径支持 fs://、http:// 协议、base64
  function picBrowser(param) {
    try {
      if (!param) throw '请传入必填项!';
      if (!param.picList) throw '请传入图片列表!';
    } catch (err) {
      alert('工具库picBrowser函数异常：' + err);
      return;
    }
    param.style = param.style || {};
    // 需要引入imageBrowser模块
    var imageBrowser = api.require('imageBrowser');
    imageBrowser.openImages({
      imageUrls: param.picList,
      activeIndex: param.index || 0,
      bg: param.bg || '#000'
    }, function (ret, err) {});
  }

  // 申请权限
  function applyPermission(permission, callback) {
    if (!isEmpty(permission, '权限')) return;
    var permissions = ['camera', 'contacts', 'contacts-r', 'contacts-w', 'microphone', 'photos', 'location', 'locationAlways', 'notification', 'calendar', 'calendar-r', 'calendar-w',
      'phone', 'phone-call', 'phone-r', 'phone-r-log', 'phone-w-log', 'sensor', 'sms', 'sms-s', 'sms-r', 'storage', 'storage-r', 'storage-w'];
    var result = null;
    for (var i = 0; i < permissions.length; i++) {
      if (permissions[i] == permission) {
        result = permission;
      }
    }
    if (!isEmpty(result, '没有找到该权限', true)) return;
    api.requestPermission({
      list: [permission],
      code: 100001
    }, function (ret, err) {
      if (!callback) return;
      setTimeout(function () {
        callback(ret.list[0].granted);
      }, 100);
    });
  }

  // app提醒用户(默认开始震动,声音,闪光灯)
  function remind(param, callback) {
    param = param || {};
    param.vibrate = param.vibrate || [500, 500];
    param.sound = param.sound || 'default';
    param.light = param.light || true;
    param.notify = param.notify || null;
    param.alarm = param.alarm || null;
    api.notification({
      vibrate: param.vibrate,
      sound: param.sound,
      light: param.light,
      notify: param.notify,
      alarm: param.alarm
    }, function (ret, err) {
      if (callback && param.notify && param.notify) {
        callback(ret, err);
      }
    });
  }

  // 监听返回手势退出app
  function exitApp() {
    var count = 0;  // 点击返回的次数
    var firstTime, secondTime; // 第一次点击的时间和第二次点击的时间
    // 监听返回键
    api.addEventListener({
      name: 'keyback'
    }, function (ret) {
      if (count == 0) { //如果之前没有点击返回
        toast('再按一次返回即退出'); // 提示用户再次点击会退出app
        count = 1;  // 更新点击返回的次数为1
        firstTime = new Date().getTime(); //记录第一次点击返回的时间
      } else if (count == 1) {  // 如果之前已经点击过一次返回
        secondTime = new Date().getTime(); // 记录第二次点击返回的时间
        if (secondTime - firstTime < 2000) { // 若第二次点击的时间与第一次点击的时间小于3s则关闭app
          api.closeWidget({});
          count = 0;
        } else {  // 反之则认为用户不像退出app，此次为第一次触发
          console.log(123456);
          count = 1;
          firstTime = new Date().getTime();
        }
      }
    });
  }

  // 完整的请求
  // wr.ajax({
  //   url: '/xxx/yyy',
  //   data: {
  //     xxx: xxx,
  //     yyy: yyy
  //   },
  //   success: function(ret) {
  //     console.log(JSON.stringify(ret));
  //   },
  //   fail: function(err) {
  //     console.log(JSON.stringify(ret));
  //   }
  // });
  function ajax(params, duration) {
    if (!params || !params.url) return false;
    var key = true;
    duration = duration || 2000;

    // 获取token
    if (!params.data || (params.data && !params.data.token)) { //如果没有token
      wr.getStorage('token') ? params.data.token = wr.getStorage('token') : '';
    }

    // 检查网络
    if (getNet() != -1) {
      onlyAjax(params);
    } else {
      var timer = setInterval(function () {
        if (key) {
          api.alert({
            title: '网络错误',
            msg: '请检查你的网络设置!',
          });
        }
        key = false;
        if (getNet() != -1) {
          clearInterval(timer);
          onlyAjax(params);
        }
      }, duration);
    }
  }

  // 纯粹的请求
  function onlyAjax(params) {
    api.ajax({
      url: config.url + params.url,
      method: params.method ? params.method : 'post', // 不传递默认为post
      headers: {
        'Content-Type': params.body && 'application/json'
      },
      timeout: 10,
      data: {
        body: params.body && params.body,
        values: params.data,
        files: params.files,
      }
    }, function (ret, err) {
      if (ret) {
        if (ret.code == 0) { // 获取正确数据
          if (params.disCode) { // 回调的部分情况只需要ret.data中的数据
            params.success && params.success(ret.data);
          } else {
            params.success && params.success(ret);
          }
        } else {  // code不为0
          // 提示及处理
          _ajaxErrcode(ret);
          if (params.disCode) {
            params.fail && params.fail(ret.data);
          } else {
            params.fail && params.fail(ret);
          }
        }
      } else {  //接口等其他异常错误 一般报404 系统错误
        if (getNet() != -1) {
          api.alert({
            msg: JSON.stringify(err),
            duration: 2000,
            location: 'bottom'
          });
        }
      }
    });
  }

  // ajax特殊值处理
  function _ajaxErrcode(ret) {
    // 特殊值提示
    var errs = {
      94: "账号需要实名认证",
      96: "账号过期，请重新登陆",
      999: "抱歉，出现了一个未知错误"
    };
    // 信息
    var info;
    if (ret.code && errs[ret.code]) { // 特殊值
      info = errs[ret.code];
    } else if (ret.code && !errs[ret.code]) { // 常用值
      info = ret.info || ret.msg || ret.message;
    } else { // 未知
      info = errs[999];
    }
    // 弹出信息
    toast(info);
    if (ret.code == 94) {
      api.confirm({
        title: '提示',
        msg: '当前用户需要进行实名认证，是否前去实名认证逻辑？',
        buttons:['确定', '取消']
      },function(ret, err){
        if(ret.buttonIndex == 1){
          alert('实名认证逻辑：wr.js at 895行');
        }
      });
    } else if (ret.code == 96) {
      rmStorage('token');
      openWin('common', 'login');
    }
  }

  // 获取网络状态
  function getNet() {
    var s = api.connectionType.toLowerCase();
    if (s.indexOf('wifi') !== -1) return 'wifi';
    if (s.indexOf('2g') !== -1) return '2g';
    if (s.indexOf('3g') !== -1) return '3g';
    if (s.indexOf('4g') !== -1) return '4g';
    if (s.indexOf('5g') !== -1) return '5g';
    return -1;
  }

  // 获取本地缓存对象
  function getLocalStorage() {
    var ls = window.localStorage;
    if (getSystem().indexOf('android') != -1) {
      ls = os.localStorage();
    }
    return ls;
  };

  // 设置本地缓存中的某个值
  function setStorage(key, value) {
    if (arguments.length === 2) {
      if (typeof value == 'object') {
        value = JSON.stringify(value);
        value = 'obj-' + value;
      } else {
        value = 'str-' + value;
      }
      var ls = getLocalStorage();
      if (ls) {
        ls.setItem(key, value);
      }
    }
  }

  // 获取本地缓存的某个值
  function getStorage(key) {
    var ls = getLocalStorage();
    if (ls) {
      key = ls.getItem(key);
      if (!key) {
        return;
      }
      if (key.indexOf('obj-') === 0) {
        key = key.slice(4);
        return JSON.parse(key);
      } else if (key.indexOf('str-') === 0) {
        return key.slice(4);
      }
    }
  }

  // 删除本地缓存的某个值
  function rmStorage(key) {
    var ls = getLocalStorage();
    if (ls && key) {
      ls.removeItem(key);
    }
  }

  // 清空本地缓存所有
  function clearStorage() {
    var ls = getLocalStorage();
    if (ls) {
      ls.clear();
    }
  }

  // 兼容沉浸式头部
  function statusBar(el) {
    el = el || document.getElementsByTagName('header')[0] || document.getElementsByClassName('header')[0] || document.getElementById('header');
    if (!el) {
      console.warn('$api.fixStatusBar Function need el param, el param must be DOM Element');
      return 0;
    }
    el.style.paddingTop = api.safeArea.top + 'px';
    return el.offsetHeight;
  };

  // 进行MD5签名
  function setParamObjMd5(ParamObj) {
    if (typeof ParamObj != 'object') {
      console.log("传入加密的参数不是对象")
      return
    }
    // 取得前10位时间戳(秒)
    var timestamp = (String(new Date().getTime())).substring(0, 10);
    // 每个接口多传递一个timestamp参数；
    ParamObj.timestamp = timestamp;

    // 排序,先变成数组，再排序
    var ParamArr = [];
    for (var key in ParamObj) {
      ParamArr.push(key)
    }
    ParamArr = ParamArr.sort();
    // 拼接
    for (var i = 0, newStr = ''; i < ParamArr.length; i++) {
      if (typeof ParamObj[ParamArr[i]] == 'object') {
        ParamObj[ParamArr[i]] = JSON.stringify(ParamObj[ParamArr[i]]);
      }
      newStr += ParamArr[i] + '=' + ParamObj[ParamArr[i]] + '&'
    }

    // 没有传参的情况
    newStr = newStr ? newStr : '&';
    // console.log(newStr);

    // 再拼接一个约定的加密字符串
    // 后端约定的字符串
    var promissStr = '0R2Rz$Gc25H0R97ZmGaQtwXd*Op0s88U';
    // 约定的promissStr加密
    promissStr = hex_md5(promissStr);
    // MD5加密
    var lastSendParam = hex_md5(newStr + promissStr);
    // console.log('sign'+lastSendParam);
    // 需要RSA加密的时候注释下面的return;
    return lastSendParam;
    // var lastData = setParamRSA(lastSendParam);
  }

  // 进行RSA加密
  function setParamRSA(param) {
    var encrypt = new JSEncrypt();
    // JSON化
    var data = JSON.stringify(param);
    // console.log(data);
    var len = data.length;
    var dataArr = [];
    var publicV = '-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8rPqGGsar+BWI7vAtaaDOqphy41j5186hCU9DcchV4HWiv0HvQ3KXAEqHfZiAHZSyMSRMmDZVnqJwCVWFvKUPqU1RsCPZ9Imk+9ZXVkM3DDdw74v/s6YMNx8cTuxybRCJUfOKbyC79cnHgmQqqkODv+EnprBtNKE4k8g90jNmbwIDAQAB-----END PUBLIC KEY-----';
    // 设置公钥
    encrypt.setPublicKey(publicV);
    // 当data.length>117最大长度的时候，1-100为一组，101-200为一组，依次
    if (len > 117) {
      // 大于长度的时候组数
      var arrNum = Math.ceil(len / 100);
      for (var i = 0; i < arrNum; i++) {
        dataArr[i] = data.substring(i * 100, (i + 1) * 100);
        // console.log(dataArr[i].length);
        // 用公钥加密
        dataArr[i] = encrypt.encrypt(dataArr[i]);
      }
    } else {
      // 用公钥加密
      dataArr[0] = encrypt.encrypt(data);
    }
    var dataStr = dataArr.join(',');
    console.log('dataStr ：' + dataStr);
    return dataStr;
    // RSA加密结束
  }

  // 判断操作系统 (可以根据返回字符串的首字母来判断操作系统，再针对性的写逻辑)
  function getSystem() {
    var version = navigator.userAgent;
    if (version.indexOf('Android') > -1 || version.indexOf('Linux') > -1) {
      return 'android';
    } else if (!!version.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)) {
      return 'ios';
    } else if (version.indexOf("Windows NT") != -1) {
      return 'windows';
    } else {
      return 'other';
    }
  }

  // 遮罩公共动画
  function toggleMask() {
    // 尝试捕获遮罩元素
    var elActionModal = document.getElementsByClassName('actionModal')[0];
    // 如果遮罩存在则关闭
    if (elActionModal) {
      // 关闭动画
      elActionModal.style.background = 'rgba(0, 0, 0, 0)';
      setTimeout(function () {
        elActionModal.parentNode.removeChild(elActionModal); //让元素彻底消失（方便下一次点击创造并打开）
      }, 200);
      // 关闭模态（apicloud部分）
      // 发送模态框事件
      /**
       * 关闭遮罩的同时发送关闭模态框事件，页面监听到后进行模态框关闭的操作
       */
      api.sendEvent({
        name: 'closeModal',
        extra: {}
      });
      // 关闭模态（apicloud部分）
    } else { // 如果遮罩不存在则打开
      // 创造遮罩元素
      var actionModal = "<div tapmode class='actionModal' style='display: none;position: fixed;top: 0;left: 0;z-index: 9999;box-sizing: border-box;width: 100%;height: 100%;overflow: hidden;transition: all .2s linear;background: rgba(0, 0, 0, 0);padding:'.3rem 1rem;'></div>";
      document.getElementsByTagName('body')[0].insertAdjacentHTML('beforeend', actionModal);
      // 捕获创造的遮罩元素
      elActionModal = document.getElementsByClassName('actionModal')[0];
      // 打开动画
      elActionModal.style.display = 'block';
      setTimeout(function () {
        elActionModal.style.background = 'rgba(0, 0, 0, .6)';
      }, 5);
      // 稍许延时后给这遮罩元素添加遮罩公共动画事件(用作下一次点击关闭)
      setTimeout(function () {
        elActionModal.addEventListener("click", function (e) {
          wr.toggleMask();
        }, true);
      }, 500);
      // 关闭遮罩（apicloud部分）
      // 监听模态框事件
      /**
       * 模态框打开后用户点击关闭模态框触发此事件将创造出的遮罩彻底消失（方便下一次点击打开）
       */
      api.addEventListener({
        name: 'closeMask'
      }, function (ret, err) {
        if (ret) {
          elActionModal.parentNode.removeChild(elActionModal);
        }
      });
      // 关闭遮罩（apicloud部分）
    }
  }

  //时间戳转成日期
  function toDate(timestamp) {
    try {
      if (getType(timestamp) != 'number') throw '参数' + timestamp + '[timestamp]不是一个数字!';
      if ((timestamp + '').length != 10 && (timestamp + '').length != 13) throw '参数' + timestamp + '[timestamp]不是一个正确的时间戳格式!';
    } catch (err) {
      alert('工具库sliceArr函数异常：' + err);
      return;
    }
    var date = 0;
    if ((timestamp.toString()).length == 10) {
      date = new Date(timestamp * 1000); //时间戳为10位需*1000
    } else {
      date = new Date(timestamp);
    }
    var Y = add0(date.getFullYear());
    var M = add0(date.getMonth() + 1);
    var D = add0(date.getDate());
    var h = add0(date.getHours());
    var m = add0(date.getMinutes());
    var s = add0(date.getSeconds());
    return [Y, M, D, h, m, s];
  }

  // 时间戳形式的时间段转为时间形式的时间段(倒计时推荐使用)
  function durationToTime(difference) {
    try {
      if (getType(difference) != 'number') throw '参数' + difference + '[difference]不是一个数字!';
      if (difference <= 0) throw '参数' + difference + '[difference]小于0!'; // 时间差为负
    } catch (err) {
      alert('工具库sliceArr函数异常：' + err);
      return;
    }
    // 将时间戳形式的时间差转为日期形式的时间差
    var date = parseInt(difference / (1000 * 60 * 60 * 24));
    difference = difference - date * 1000 * 60 * 60 * 24;
    var hour = parseInt(difference / (1000 * 60 * 60));
    difference = difference - hour * 1000 * 60 * 60;
    var min = parseInt(difference / (1000 * 60));
    difference = difference - min * 1000 * 60;
    var second = parseInt(difference / 1000);
    // 返回时间段
    return [add0(date), add0(hour), add0(min), add0(second)];
  }

  // 十以内补零
  function add0(num) {
    try {
      if (getType(num) != 'number') throw '参数' + num + '[num]不是一个数字!';
    } catch (err) {
      alert('工具库sliceArr函数异常：' + err);
      return;
    }
    return num < 10 ? '0' + num.toString() : num.toString();
  }

  // 数组截取前n位
  function sliceArr(arr, maxLength) {
    try {
      if (getType(arr) != 'Array') throw '参数' + arr + '[arr]不是一个数组!';
      if (getType(maxLength) != 'number') throw '参数' + maxLength + '[maxLength]不是一个数字!';
    } catch (err) {
      alert('工具库sliceArr函数异常：' + err);
      return;
    }
    if (arr.length > maxLength) {
      var cacheArr = [];
      for (var i = 0; i < maxLength; i++) {
        cacheArr.push(arr[i]);
      }
      return cacheArr;
    }
    return arr;
  }

  // 变量或数组的非空验证
  function isEmpty(variable, isInfo, allInfo) {
    allInfo = allInfo || false;
    if (getType(variable) != 'Array') {
      if (!variable || variable <= 0) {
        if (isInfo && allInfo) {
          toast(isInfo, 1500, 'middle');
        } else if (isInfo) {
          toast(isInfo + '不能为空', 1500, 'middle');
        }
        return false;
      } else {
        return true;
      }
    } else {
      if (!variable || variable.length == 0) {
        if (isInfo && allInfo) {
          toast(isInfo, 1500, 'middle');
        } else if (isInfo) {
          toast(isInfo + '不能为空', 1500, 'middle');
        }
        return false;
      } else {
        return true;
      }
    }
  }

  // 汉人姓名验证（2-4）
  function realnameTest(realname, isInfo) {
    isInfo = isInfo || true;
    if (!(/^[\u4e00-\u9fa5]{2,4}$/.test(realname))) {
      if (isInfo) {
        wr.toast('请输入正确的姓名!', 1500, 'middle');
      }
      return false;
    }
    return true;
  }

  // 手机号验证
  function mobileTest(mobile, isInfo) {
    isInfo = isInfo || true;
    if (!(/^[1]([3-9])[0-9]{9}$/.test(mobile))) {
      if (isInfo) {
        wr.toast('请输入正确的手机号!', 1500, 'middle');
      }
      return false;
    }
    return true;
  }

  // 身份证号验证
  function idTest(idNumber, isInfo) {
    isInfo = isInfo || true;
    if (!(/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(idNumber))) {
      if (isInfo) {
        wr.toast('请输入正确的身份证号!', 1500, 'middle');
      }
      return false;
    }
    return true;
  }

  // 邮箱验证
  function emailTest(email, isInfo) {
    isInfo = isInfo || true;
    if (!(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(email))) {
      if (isInfo) {
        wr.toast('请输入正确的邮箱!', 1500, 'middle');
      }
      return false;
    }
    return true;
  }

  // 指定范围的数字验证
  function numberTest(number, min, max, info) {
    number = parseFloat(number);
    if (!(/^[0-9]*$/.test(number)) || number > max || number < min) {
      if (info) {
        wr.toast('请输入大小为' + min + '到' + max + '间的' + info + '!', 1500, 'middle');
      }
      return false;
    }
    return true;
  }

  // 指定长度的字符串验证
  function strLength(el, min, max, info) {
    el = el.toString();
    if (el.length > max || el.length < min) {
      if (info) {
        wr.toast('请输入' + min + '到' + max + '位的' + info + '!', 1500, 'middle');
      }
      return false;
    }
    return true;
  }

  // 类型判断
  function getType(obj) {
    var type = typeof obj;
    if (type != "object") {
      return type;
    }
    return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');
  }

  // 返回对象的长度
  function objLen(obj) {
    return Object.keys(obj).length;
  }

  // 屏蔽当前调用页面的所有console.log输出
  function disLog() {
    console.log = function () { };
  }

  // 防抖 避免短时间内的重复提交(只支持事件监听)
  function debounce(callback, delay) {
    var timer;
    return function () {
      if (timer) {
        clearTimeout(timer);
      }
      timer = setTimeout(function () {
        callback();
      }, delay)
    }
  }

  // 验证表单重复提交(强制，需ajax配合)
  function noRepeat(callback) {
    // 检查是否有此钥匙
    try {
      if (!requestKey && requestKey != false) throw 'wr.noRepeat方法缺少js全局钥匙requestKey!';
    } catch (err) {
      alert('工具库sliceArr函数异常：' + err);
      return;
    }
    // 第一次
    if (requestKey == true) {
      requestKey = false;
      callback.apply(that, [!requestKey]);
    } else if (requestKey == false) { // 第二次
      callback.apply(that, [requestKey]);
    }
  }

  // 验证表单重复提交(强制，需ajax配合)
  function noRepeatVue(that, callback) {
    try {
      if (!that.requestKey && that.requestKey != false) throw 'wr.noRepeatVue方法缺少vue全局钥匙this.requestKey!';
    } catch (err) {
      alert('工具库sliceArr函数异常：' + err);
      return;
    }
    // 第一次
    if (that.requestKey == true) {
      that.requestKey = false;
      callback.apply(that, [!that.requestKey]);
    } else if (that.requestKey == false) { // 第二次
      callback.apply(that, [that.requestKey]);
    }
  }

  var model = {
    // apicloud专属
    ready: ready, // 准备工作
    isApi: isApi, // 判断是否apicloud环境
    openWin: openWin, // 打开一个指定路径的页面（可带页面参数）
    openCommonWin: openCommonWin, // 打开一个指定路径并带有公共头部的页面（可带页面参数）
    listenHeadEvent: listenHeadEvent, // 监听公共头部的自定义事件
    openCommonUrl: openCommonUrl, // 打开一个指定url并带有公共头部的外链页面
    openModal: openModal, // 打开模态框
    ifLogin: ifLogin, // 检测登录状态，如无登录则跳转指定页面
    toast: toast, // 弹一个toast
    addLastInfo: addLastInfo, // 列表内容底部提醒
    removeLastInfo: removeLastInfo, // 删除没有内容时的提醒
    setText: setText, // 设置文本到粘贴板  (需要模块)
    getText: getText, // 从粘贴板获取文本  (需要模块)
    selClipPhoto: selClipPhoto,   // 选择一张能够裁剪的图片或照片 (需要模块)
    picClip: picClip,   // 图片裁剪  (需要模块)
    _picClipSave: _picClipSave,  // 图片裁剪保存(私有) (需要模块)
    selMoreMedia: selMoreMedia, // 选择单个或多个媒体 (需要模块)
    longpress: longpress, // 长按保存图片
    downloadPic: downloadPic, // 保存图片
    shareWxWeb: shareWxWeb, // 分享微信网页(需要模块)
    shareQQWeb: shareQQWeb, // 分享QQ网页(需要模块)
    wxPay: wxPay,  // 微信支付（需要模块）
    aliPay: aliPay,  //支付宝支付 (需要模块)
    openSignBoard: openSignBoard, // 打开签字板 (需要模块)
    _reSignBoard: _reSignBoard, // 重置签字板 (需要模块)
    _closeSignBoard: _closeSignBoard, // 关闭签字板 (需要模块)
    picBrowser: picBrowser,  // 图片查阅器 路径支持 fs://、http:// 协议、base64 (需要模块)
    applyPermission: applyPermission,  // 申请权限(针对sdk等级为26或以上)
    remind: remind,  // app提醒用户(默认开始震动,声音,闪光灯)
    exitApp: exitApp,  // 监听返回手势退出app
    ajax: ajax,  // 完整的请求
    onlyAjax: onlyAjax,  // 纯粹的请求
    getNet: getNet,  // 获取网络
    getLocalStorage: getLocalStorage,  // 获取本地缓存对象
    setStorage: setStorage,  // 设置本地缓存中的某个值
    getStorage: getStorage,  // 获取本地缓存的某个值
    rmStorage: rmStorage,  // 删除本地缓存的某个值
    clearStorage: clearStorage,  // 清空本地缓存所有
    statusBar: statusBar,  // 兼容沉浸式头部
    // 前端通用
    setParamObjMd5: setParamObjMd5, // 进行MD5签名
    setParamRSA: setParamRSA, // 进行RSA加密
    getSystem: getSystem,  // 判断操作系统
    toggleMask: toggleMask, // 打开/关闭遮罩层
    toDate: toDate, // 时间戳转成日期
    durationToTime: durationToTime, // 时间戳形式的时间段转为时间形式的时间段(倒计时推荐使用)
    add0: add0, // 十以内补零
    sliceArr: sliceArr, // 数组截取前n位
    isEmpty: isEmpty, // 变量或数组的非空验证
    realnameTest: realnameTest, // 真实姓名验证
    mobileTest: mobileTest, // 手机号验证
    idTest: idTest, // 身份证验证
    emailTest: emailTest, // 邮箱验证
    numberTest: numberTest, // 指定一个数字大小的验证
    strLength: strLength, // 指定长度的字符串验证
    getType: getType, // 类型判断
    objLen: objLen,  // 返回对象的长度
    disLog: disLog, // 屏蔽当前调用页面的所有console.log输出
    debounce: debounce, // 防抖 避免短时间内的重复提交(避免恶意提现等...)
    noRepeat: noRepeat, // 强制验证表单重复提交(需传全局requestKey以及ajax配合)
    noRepeatVue: noRepeatVue // 强制验证表单重复提交(需传全局requestKey以及ajax配合)
  }

  return model;
})();
